package com.jade.framework.base.security;

import java.security.BasicPermission;
import java.security.Permission;
import java.security.PermissionCollection;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * Action权限.
 *
 * @author dwzhang
 * @version 1.0 13-4-18 上午9:21
 */
public class ActionPermission extends BasicPermission
{
    private String actions = null;
    private transient Set<String> set = null;
    private transient boolean actionWildcard;

    /**
     * Creates a new BasicPermission with the specified name.
     * Name is the symbolic name of the permission, such as
     * "setFactory",
     * "print.queueJob", or "topLevelWindow", etc.
     *
     * @param name the name of the BasicPermission.
     * @throws NullPointerException     if <code>name</code> is <code>null</code>.
     * @throws IllegalArgumentException if <code>name</code> is empty.
     */
    public ActionPermission(String name)
    {
        super(name);
        setActions(null);
    }

    /**
     * Creates a new BasicPermission object with the specified name.
     * The name is the symbolic name of the BasicPermission, and the
     * actions String is currently unused.
     *
     * @param name    the name of the BasicPermission.
     * @param actions ignored.
     * @throws NullPointerException     if <code>name</code> is <code>null</code>.
     * @throws IllegalArgumentException if <code>name</code> is empty.
     */
    public ActionPermission(String name, String actions)
    {
        super(name, actions);
        setActions(actions);
    }

    public void setActions(String actions)
    {
        if (actions == null) {
            actionWildcard = false;
            this.actions = actions;
        }
        else {
            this.actions = actions;
            this.actionWildcard = "*".equals(actions);
        }
    }

    private Set getSet()
    {
        if (set == null && actions != null) {
            set = new HashSet<String>();
            String[] array = StringUtils.split(actions, ',');
            CollectionUtils.addAll(set, array);
        }
        return set;
    }

    /**
     * Returns the canonical string representation of the actions,
     * which currently is the empty string "", since there are no actions for
     * a BasicPermission.
     *
     * @return the empty string "".
     */
    public String getActions()
    {
        return actions;
    }

    /**
     * Checks if the specified permission is "implied" by
     * this object.
     * <p/>
     * More specifically, this method returns true if:<p>
     * <ul>
     * <li> <i>p</i>'s class is the same as this object's class, and<p>
     * <li> <i>p</i>'s name equals or (in the case of wildcards)
     * is implied by this object's
     * name. For example, "a.b.*" implies "a.b.c".
     * </ul>
     *
     * @param p the permission to check against.
     * @return true if the passed permission is equal to or
     *         implied by this permission, false otherwise.
     */
    public boolean implies(Permission p)
    {
        if (super.implies(p)) {
            ActionPermission that = (ActionPermission)p;

            if (this.actionWildcard) {
                //任何 Actions 都可以接受
                return true;
            }
            else {
                if (that.actionWildcard) {
                    //Actions == "*" 表示都匹配
                    return true;
                }
                else {
                    Set set = getSet();
                    return set != null && set.contains(that.actions);
                }
            }
        }
        return false;
    }

    /**
     * Returns a new PermissionCollection object for storing BasicPermission
     * objects.
     * <p/>
     * A BasicPermissionCollection stores a collection of
     * BasicPermission permissions.
     * <p/>
     * <p>BasicPermission objects must be stored in a manner that allows them
     * to be inserted in any order, but that also enables the
     * PermissionCollection <code>implies</code> method
     * to be implemented in an efficient (and consistent) manner.
     *
     * @return a new PermissionCollection object suitable for
     *         storing BasicPermissions.
     */

    public PermissionCollection newPermissionCollection()
    {
        return new ActionPermissionCollection();
    }
}
